package com.ivt.dao.impl;

import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Repository;

import com.ivt.dao.SpecificDao;
import com.ivt.model.Attendance;
import com.ivt.model.Classes;
import com.ivt.model.Courses;
import com.ivt.model.Notice;
import com.ivt.model.Role;
import com.ivt.model.Student;
import com.ivt.model.Teacher;
import com.ivt.model.User;
import com.ivt.model.view.QueryCriteria;

@Repository
public class SpecificDaoImpl implements SpecificDao {

	@PersistenceContext
	private EntityManager em;

	// TODO
	@SuppressWarnings("unchecked")
	@Override
	public List<User> findAgent(User owner) {
		StringBuffer sb = new StringBuffer(
				"select u from User u , Group g where u.group.id=g.id and g.owner=:owner and g.role = :role ");
		Query query = em.createQuery(sb.toString());

		query.setParameter("owner", owner);
		query.setParameter("role", "agent");

		return query.getResultList();
	}

	private Query createHqlQuery(String hql, int offset, int limit) {
		Query query = em.createQuery(hql.toString());
		if (offset < 0) {
			offset = 0;
		}
		query.setFirstResult(offset);
		if (limit > 0) {
			query.setMaxResults(limit);
		}
		return query;
	}

	protected Query splitCountQuery(QueryCriteria queryCriteria, Class<?> clazz) {
		Query query = null;
		StringBuffer sb = new StringBuffer("select count(c) from ");
		sb.append(clazz.getName()).append(" c   where 1=1 ");
		if (null != queryCriteria
				&& MapUtils.isNotEmpty(queryCriteria.findCriteria())) {
			Map<String, Object> json = queryCriteria.findCriteria();
			Set<String> keys = json.keySet();
			if (CollectionUtils.isNotEmpty(keys)) {
				for (String key : keys) {
					Object val = json.get(key);
					if (null != val && StringUtils.isNotBlank(val.toString()))
						sb.append(" and c.").append(key).append("=")
								.append(":").append(key);
				}

			}
		}
		query = em.createQuery(sb.toString());

		if (null != queryCriteria
				&& MapUtils.isNotEmpty(queryCriteria.findCriteria())) {
			Map<String, Object> json = queryCriteria.findCriteria();
			Set<String> keys = json.keySet();
			if (CollectionUtils.isNotEmpty(keys)) {
				for (String key : keys) {
					Object val = json.get(key);
					if (null != val && StringUtils.isNotBlank(val.toString()))
						query.setParameter(key, val);
				}
			}
		}

		return query;
	}

	protected Query splitQuery(QueryCriteria queryCriteria, Class<?> clazz) {
		Query query = null;
		StringBuffer sb = new StringBuffer("select c from ");
		sb.append(clazz.getName()).append(" c where 1=1 ");
		if (null != queryCriteria
				&& MapUtils.isNotEmpty(queryCriteria.findCriteria())) {
			Map<String, Object> json = queryCriteria.findCriteria();
			Set<String> keys = json.keySet();
			if (CollectionUtils.isNotEmpty(keys)) {
				for (String key : keys) {
					Object val = json.get(key);
					if (null != val && StringUtils.isNotBlank(val.toString()))
						sb.append(" and c.").append(key).append("=")
								.append(":").append(key);
				}

			}
		}
		query = em.createQuery(sb.toString());

		if (null != queryCriteria
				&& MapUtils.isNotEmpty(queryCriteria.findCriteria())) {
			Map<String, Object> json = queryCriteria.findCriteria();
			Set<String> keys = json.keySet();
			if (CollectionUtils.isNotEmpty(keys)) {
				for (String key : keys) {
					Object val = json.get(key);
					if (null != val && StringUtils.isNotBlank(val.toString()))
						query.setParameter(key, val);

				}

			}
		}

		return query;
	}

	// 班级表
	@Override
	public long queryClassesCount(QueryCriteria queryCriteria) {

		Query query = splitCountQuery(queryCriteria, Classes.class);

		return (Long) query.getSingleResult();
	}

	@Override
	public List<Classes> queryClasses(QueryCriteria queryCriteria) {
		Query query = splitQuery(queryCriteria, Classes.class);

		query.setFirstResult(queryCriteria.getOffset());
		query.setMaxResults(queryCriteria.getPageSize());

		return query.getResultList();
	}

	// 学生表
	@Override
	public List<Student> queryStudent(QueryCriteria queryCriteria) {
		Query query = splitQuery(queryCriteria, Student.class);

		query.setFirstResult(queryCriteria.getOffset());
		query.setMaxResults(queryCriteria.getPageSize());

		return query.getResultList();
	}

	@Override
	public long queryStudentCount(QueryCriteria queryCriteria) {
		Query query = splitCountQuery(queryCriteria, Student.class);

		return (Long) query.getSingleResult();
	}

	// 公告表
	@Override
	public long queryNoticeCount(QueryCriteria queryCriteria) {
		Query query = splitCountQuery(queryCriteria, Notice.class);

		return (Long) query.getSingleResult();
	}

	@Override
	public List<Notice> queryNotice(QueryCriteria queryCriteria) {
		Query query = splitQuery(queryCriteria, Notice.class);

		query.setFirstResult(queryCriteria.getOffset());
		query.setMaxResults(queryCriteria.getPageSize());

		return query.getResultList();
	}

	// 角色表
	@Override
	public long queryRoleCount(QueryCriteria queryCriteria) {
		Query query = splitCountQuery(queryCriteria, Role.class);

		return (Long) query.getSingleResult();
	}

	@Override
	public List<Role> queryRole(QueryCriteria queryCriteria) {
		Query query = splitQuery(queryCriteria, Role.class);

		query.setFirstResult(queryCriteria.getOffset());
		query.setMaxResults(queryCriteria.getPageSize());

		return query.getResultList();
	}

	// 出勤表
	@Override
	public long queryAttendanceCount(QueryCriteria queryCriteria) {
		Query query = splitCountQuery(queryCriteria, Attendance.class);

		return (Long) query.getSingleResult();
	}

	@Override
	public List<Attendance> queryAttendance(QueryCriteria queryCriteria) {
		Query query = splitQuery(queryCriteria, Attendance.class);

		query.setFirstResult(queryCriteria.getOffset());
		query.setMaxResults(queryCriteria.getPageSize());

		return query.getResultList();
	}

	@Override
	public long queryTeacherCount(QueryCriteria queryCriteria) {
		Query query = splitCountQuery(queryCriteria, Teacher.class);

		return (Long) query.getSingleResult();
	}

	@Override
	public List<Teacher> queryTeacher(QueryCriteria queryCriteria) {
		Query query = splitQuery(queryCriteria, Teacher.class);

		query.setFirstResult(queryCriteria.getOffset());
		query.setMaxResults(queryCriteria.getPageSize());

		return query.getResultList();
	}

	@Override
	public long queryCoursesCount(QueryCriteria queryCriteria) {
		Query query = splitCountQuery(queryCriteria, Courses.class);

		return (Long) query.getSingleResult();
	}

	@Override
	public List<Courses> queryCourses(QueryCriteria queryCriteria) {
		Query query = splitQuery(queryCriteria, Courses.class);

		query.setFirstResult(queryCriteria.getOffset());
		query.setMaxResults(queryCriteria.getPageSize());

		return query.getResultList();
	}

}
